package wangwenjun.phase2.concurrencypattern.readwritelockseparation.demo01.framework;

/**
 *
 * 其设计成包可见以透明其实现细节，让使用者只用专注于对接口的调用
 * @author ChangLiang
 * @date 2020/6/12
 */
class ReadLock implements Lock {

    private final ReadWriteLockFactoryImpl readWriteLock;

    ReadLock(ReadWriteLockFactoryImpl readWriteLock)
    {
        this.readWriteLock = readWriteLock;
    }

    @Override
    public void lock() throws InterruptedException {
        // 使用Mutex 作为锁
        synchronized (readWriteLock.getMutex()) {
            /**
             * 若此时有线程在进行写操作，或者有写线程在等待并且偏向写锁的标识为true 时，就会无
             * 法获得读锁，只能被挂起
             */
            while (readWriteLock.getWritingWriters() > 0
                    || (readWriteLock.getPreferWriter() && readWriteLock.getWaitingWriters() > 0)
            ) {
                readWriteLock.getMutex().wait();
            }
            // 成功获得读锁， 并且使readingReaders 的数量增加
            readWriteLock.incrementReadingReaders();
        }
    }

    @Override
    public void unlock() {
        /**
         * 使用Mutex 作为锁，并且进行同步
         */
        synchronized (readWriteLock.getMutex()) {
            // 释放锁的过程就是使得当前reading 的数量减一
            readWriteLock.decrementReadingReaders();
            // 将preferWriter 设置为true ，可以使得writer 线程获得更多的机会
            readWriteLock.changePrefer(true);
            // 通知唤醒与Mutex 关联monitor waitset 中的线程
            readWriteLock.getMutex().notifyAll();
        }
    }
}
